﻿namespace Monadic
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public class Continuation<R, A>
    {
        private readonly Func<Func<A, R>, R> value;

        internal Continuation(Func<Func<A, R>, R> func)
        {
            this.value = func;
        }

        public R Run(Func<A, R> k)
        {
            return value(k);
        }

        public Continuation<R, B> Select<B>(Func<A, B> selector)
        {
            return Continuation.Create<R, B>(c => value(p => c(selector(p))));
        }

        public Continuation<R, B> SelectMany<B>(Func<A, Continuation<R, B>> selector)
        {
            return Continuation.Create<R, B>(c => value(a => selector(a).value(c)));
        }

        public Continuation<R, C> SelectMany<B, C>(Func<A, Continuation<R, B>> selector, Func<A, B, C> func)
        {
            return SelectMany<C>(a => selector(a).Select<C>(b => func(a, b)));
        }
    }

    public static class Continuation
    {
        public static Continuation<R, A> Create<R, A>(Func<A> func)
        {
            return Continuation.Create<R, A>(k => k(func()));
        }

        public static Continuation<R, A> Create<R, A>(Func<A, R> func)
        {
            return Continuation.Create<R, A>(k => func(k));
        }

        public static Continuation<R, A> Create<R, A>(Func<Func<A, R>, R> func)
        {
            return new Continuation<R, A>(func);
        }
    }
}
